package item66;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 第66条：同步访问共享的可变数据
 */
public class Main01 {

    // broken - requires synchronization
    // 破损 - 需要同步
    private static volatile int nextSerialNumber = 0;
    // 错误，这个方法的目的是要确保每个调用都返回不同的值。
    public static int generateSerialNumber() {
        // 首先它读取值，然后写回一个新值，相当于原来的值再加上1.
        return nextSerialNumber++; //++ 不是原子的
    }

    private static int nextSerialNumber01 = 0;
    public static synchronized int generateSerialNumber01() {
        return nextSerialNumber01++;
    }

    private static int nextSerialNumber02 = 0;
    public static synchronized int generateSerialNumber02() {
        if (nextSerialNumber02 >= Integer.MAX_VALUE) {
            System.out.println("已经到最大了");
        }
        return nextSerialNumber02++;
    }

    private static long nextSerialNumber03 = 0;
    public static synchronized long generateSerialNumber03() {
        if (nextSerialNumber03 >= Long.MAX_VALUE) {
            System.out.println("已经到最大了");
        }
        return nextSerialNumber03++;
    }

    private static final AtomicLong nextSerialNumber04 = new AtomicLong();
    public static long generateSerialNumber04() {
        return nextSerialNumber04.getAndIncrement();
    }


    public static void main(String[] args) {
        // synchronized
        // 1.互斥
        // 2.不仅可以阻止一个线程看到对象处于不一致状态之中，
        // 它还可以保证进入同步方法或者同步代码块的每个线程，都看到由同一个锁保护的之前所有的修改效果。

        // 你可能听说过，为了提高性能，在读或写原子数据的时候，应该避免使用同步。这个建议是非常危险而错误的。
        // 为了在线程之间进行可靠的通信，也为了互拆访问，同步是必要的。
        // 不要使用Thread.stop

        /**
         * @see StopThread#main(String[])
         */
        // while(!done)
        //  i++

        // if (!done)
        //  while(true)
        //      i++;

        /**
         * @see StopThread02#main(String[])
         */
        // 如果读和写操作没有都被同步，同步就不会起作用。

        // 将可变数据限制在单个线程中。

        // 当多个线程共享可变数据的时候，每个读或写数据的线程都必须执行同步。
    }

}
